package priv.pic.to.link.main.task;

import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.tulskiy.keymaster.common.HotKey;
import com.tulskiy.keymaster.common.HotKeyListener;
import com.tulskiy.keymaster.common.Provider;
import javafx.util.Pair;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import priv.pic.to.link.main.APP;
import priv.pic.to.link.main.domain.Config;
import priv.pic.to.link.main.util.PropertiesUtil;
import priv.pic.to.link.main.util.ProviderUtil;
import priv.pic.to.link.main.util.TipUtil;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

/**
 * Created on 2018/4/27.
 */
public class PicUploadTask implements Runnable {
    private static final Random random = new Random(73);
    private static final String MD_IMG_PATTERN = "![image](http://%s/%s)";
    private static final long MAX_FILE_SIZE = 50 * 1024 * 1024;

    private static Pair<String, String> lastUpload = new Pair<>(null, null);//cache name of last cached file

    private static Config config;// configs of qiniu-cloud
    private static Clipboard clipboard;
    private static Provider provider;// for hot-key

    private static Logger logger = LoggerFactory.getLogger(APP.class);

    @Override
    public void run() {
        config = PropertiesUtil.loadConfig();
        provider = Provider.getCurrentProvider(false);
        clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();

        KeyStroke shutdownKS = KeyStroke.getKeyStroke(config.shutdownHotKey.replaceAll("\\+", " "));
        KeyStroke uploadKS = KeyStroke.getKeyStroke(config.uploadHotKey.replaceAll("\\+", " "));

        ArrayList<HotKey> hotKeys = new ArrayList<>();
        hotKeys.add(new HotKey(shutdownKS, new HotKeyListener() {
            public void onHotKey(HotKey hotKey) {
                System.out.println(hotKey);
                provider.reset();
                TipUtil.tip("Exit pic-to-link!");
                provider.stop();
            }
        }));

        //do not check the file type
        hotKeys.add(new HotKey(uploadKS, new HotKeyListener() {
            @Override
            public void onHotKey(HotKey hotKey) {
                if (!clipboard.isDataFlavorAvailable(DataFlavor.imageFlavor)
                        && !clipboard.isDataFlavorAvailable(DataFlavor.javaFileListFlavor)) {
                    return;
                }
                try {
                    action();
                } catch (Exception e) {
                    e.printStackTrace();
                    TipUtil.tip("上传失败：" + e.getMessage());
                }
            }
        }));
        ProviderUtil.registerHotKeys(provider, hotKeys);
    }

    private static void action() throws Exception {
        //get image
        byte[] bytes = getImgInBytes();
        if (bytes == null) {
            TipUtil.tip("读取数据出错!");
            return;
        }
        if (bytes.length > MAX_FILE_SIZE) {
            TipUtil.tip("too large..");
            return;
        }

        //upload
        String name = upload(bytes);

        //write to clipboard
        String link = String.format(MD_IMG_PATTERN, config.imgDomain, name);
        clipboard.setContents(new StringSelection(link), null);
        Robot robot = new Robot();
        robot.keyPress(KeyEvent.VK_CONTROL);
        robot.keyPress(KeyEvent.VK_V);
        robot.keyRelease(KeyEvent.VK_V);
        robot.keyRelease(KeyEvent.VK_CONTROL);
        TipUtil.tip("name= " + name);
        logger.info(name);
    }

    private static byte[] getImgInBytes() throws UnsupportedFlavorException, IOException {
        if (clipboard.isDataFlavorAvailable(DataFlavor.imageFlavor)) {
            BufferedImage image = (BufferedImage) clipboard.getData(DataFlavor.imageFlavor);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(image, "png", outputStream);
            outputStream.close();
            return outputStream.toByteArray();
        } else {
            File file = ((List<File>) clipboard.getData(DataFlavor.javaFileListFlavor)).get(0);
            if (!file.exists() || file.isDirectory()) {
                return null;
            }
            if (file.length() > MAX_FILE_SIZE) {
                if (!TipUtil.confirm("文件超过50M，确定上传吗？")) {
                    return null;
                }
            }
            byte[] bytes = new byte[(int) file.length()];
            FileInputStream fis = new FileInputStream(file);
            fis.read(bytes);
            fis.close();
            return bytes;
        }
    }

    private static String upload(byte[] bytes) throws Exception {
        String hash = DigestUtils.md5Hex(bytes);
        if (hash.equals(lastUpload.getKey())) {
            TipUtil.tip("不需要重复上传!");
            return lastUpload.getValue();
        }

        //构造一个带指定Zone对象的配置类
        Configuration cfg = new Configuration(Zone.zone0());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //...生成上传凭证，然后准备上传

        String key = createNameSize8();
        String upToken = config.auth.uploadToken(config.bucket);
        Response response = uploadManager.put(bytes, key, upToken);
        lastUpload = new Pair<>(hash, key);
        return key;
    }

    private static String createNameSize8() {
        int index = random.nextInt(25);
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date());
        String name = UUID.randomUUID().toString().replaceAll("-", "").substring(index, index + 8);
        return date + "/" + name;
    }
}
